package drds.plus.repository.berkeley.spi;

import drds.plus.executor.ExecuteContext;
import drds.plus.executor.command_handler.CommandHandler;
import drds.plus.executor.command_handler.CommandHandlerFactory;
import drds.plus.executor.command_handler.put.DeleteHandler;
import drds.plus.executor.command_handler.put.InsertHandler;
import drds.plus.executor.command_handler.put.ReplaceHandler;
import drds.plus.executor.command_handler.put.UpdateHandler;
import drds.plus.executor.command_handler.query.MergeQueryHandler;
import drds.plus.executor.command_handler.query.QueryHandler;
import drds.plus.executor.command_handler.query.join.IndexBlockNestedtLoopJoinHandler;
import drds.plus.executor.command_handler.query.join.IndexNestedLoopJoinHandler;
import drds.plus.executor.command_handler.query.join.SortMergeJoinHandler;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.ExecutePlan;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.dml.IPut;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.dml.PutType;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.Join;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.JoinStrategy;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.MergeQuery;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.QueryWithIndex;


public class CommandHandlerFactoryImpl implements CommandHandlerFactory {

    private CommandHandler insertHandler;
    private CommandHandler updateHandler;
    private CommandHandler deleteHandler;
    private CommandHandler replaceHandler;
    private CommandHandler queryHandler;
    private CommandHandler mergeHandler;
    private CommandHandler indexNestLoopJoinHandler;
    private CommandHandler indexBlockNestedtLoopJoinHandler;
    private CommandHandler sortMergeJoinHandler;

    private QueryHandler condensableJoinHandler;

    public CommandHandlerFactoryImpl() {
        insertHandler = new InsertHandler();
        updateHandler = new UpdateHandler();
        deleteHandler = new DeleteHandler();
        replaceHandler = new ReplaceHandler();
        queryHandler = new QueryHandler();
        mergeHandler = new MergeQueryHandler();
        indexNestLoopJoinHandler = new IndexNestedLoopJoinHandler();
        indexBlockNestedtLoopJoinHandler = new IndexBlockNestedtLoopJoinHandler();
        sortMergeJoinHandler = new SortMergeJoinHandler();
        condensableJoinHandler = new QueryHandler();

    }

    public CommandHandler getCommandHandler(ExecuteContext executeContext, ExecutePlan executePlan) {

        if (executePlan instanceof QueryWithIndex) {
            return queryHandler;
        } else if (executePlan instanceof MergeQuery) {
            return mergeHandler;
        } else if (executePlan instanceof Join) {
            boolean condensableJoin = isCondensableJoin(executePlan);
            if (condensableJoin) {
                return condensableJoinHandler;
            }
            Join join = (Join) executePlan;
            JoinStrategy joinStrategy = join.getJoinStrategy();
            switch (joinStrategy) {
                case index_nest_loop_join:
                    return indexNestLoopJoinHandler;
                case nest_loop_join:
                    return indexBlockNestedtLoopJoinHandler;
                case sort_merge_join:
                    return sortMergeJoinHandler;
                default:
                    throw new IllegalArgumentException("should not be here");
            }
        } else if (executePlan instanceof IPut) {
            IPut put = (IPut) executePlan;
            PutType putType = put.getPutType();
            switch (putType) {
                case replace:
                    return replaceHandler;
                case insert:
                    return insertHandler;
                case delete:
                    return deleteHandler;
                case update:
                    return updateHandler;
                default:
                    throw new IllegalArgumentException("should not be here");
            }
        } else {
            throw new IllegalArgumentException("should not be here");
        }
    }

    /**
     * 可以合并的join
     */
    private boolean isCondensableJoin(ExecutePlan executePlan) {
        Join join = (Join) executePlan;
        String leftNodeDataNodeId = join.getLeftNode().getDataNodeId();
        String rightNodeDataNodeId = join.getRightNode().getDataNodeId();
        if (leftNodeDataNodeId == null || rightNodeDataNodeId == null) {//[1]非空节点
            return false;
        } else if (!leftNodeDataNodeId.equals(rightNodeDataNodeId)) {//[2]节点一致
            return false;
        }

        if (join.getLeftNode() instanceof MergeQuery || join.getRightNode() instanceof MergeQuery) {//[3]节点非Merge
            return false;
        }
        boolean leftJoin = true;
        boolean rightJoin = true;
        if (join.getLeftNode() instanceof Join) {
            leftJoin = isCondensableJoin(join.getLeftNode());
        }
        if (join.getRightNode() instanceof Join) {
            rightJoin = isCondensableJoin(join.getRightNode());//[4]子节点。。。
        }

        return leftJoin & rightJoin;
    }

}
